﻿using System;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using System.Xml;
using AccountingUnitTest.Properties;
using Apache.NMS;
using Apache.NMS.Util;
using BusinessLogic;
using BusinessLogic.Dto;
using Common;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Services;

namespace AccountingUnitTest
{
    [TestClass]
    public class AccountingServicesTest
    {
        #region Setup

        private static AccountingServices services;
        private static IConnectionFactory factory;


        [ClassInitializeAttribute]
        public static void ClassInit(TestContext context)
        {
            // NOTE: ensure the nmsprovider-activemq.config file exists in the executable folder.
            factory = new NMSConnectionFactory(Constants.QUEUE_URI);

            using (var db = new WGRUSEntities())
            {
                //Check if test customer exsists - if not create
                var c = db.Customers.Find(12345678);
                if (c == null)
                {
                    c = new Customer
                    {
                        Approved = true,
                        By = "Vejle",
                        CreditLimit = 1000,
                        Email = "test@eal.dk",
                        Gade = "Boulevarden 19D",
                        Navn = "EAL",
                        Oprettet = DateTime.Now,
                        PostNr = 7100,
                        TelefonNr = 12345678
                    };
                    db.Customers.Add(c);
                }
                else
                {
                    c.Gade = "Boulevarden 19D";
                }
                c = db.Customers.Find(87654321);
                if (c != null)
                {
                    db.Customers.Remove(c);
                }

                c = db.Customers.Find(55555555);
                if (c != null)
                {
                    db.Customers.Remove(c);
                }
                db.SaveChanges();

                //Check if Items exsists - if not create
                var w = db.Items.Find("W1234");
                var g = db.Items.Find("G5678");

                if (w == null)
                {
                    w = new Item
                    {
                        Beskrivelse = "W1234-test",
                        Enhedspris = (decimal) 12.34,
                        VareId = "W1234"
                    };
                    db.Items.Add(w);
                }

                if (g == null)
                {
                    g = new Item
                    {
                        Beskrivelse = "G5678-test",
                        Enhedspris = (decimal) 56.78,
                        VareId = "G5678"
                    };
                    db.Items.Add(g);
                }

                db.SaveChanges();
                //Clean up exsisting orders
                db.Database.ExecuteSqlCommand("DELETE FROM OrderLine");
                db.Database.ExecuteSqlCommand("DELETE FROM Payment");
                db.Database.ExecuteSqlCommand("DELETE FROM [Order]");
            }

            services = new AccountingServices();
            //xmlOrder = File.ReadAllText(@"C:\Users\kbr\Dropbox\Dokumenter\Fag\PBA - Systemintegration\WGRUS\Accounting\AccountingUnitTest\bin\Debug\TestData\TestOrder.xml");
        }


        [TestInitialize]
        public void TestSetup()
        {
        }

        [TestCleanup()]
        public void Cleanup()
        {
            //Cleanup Queues
            using (IConnection connection = factory.CreateConnection())
            using (ISession session = connection.CreateSession())
            {
                IDestination destination = SessionUtil.GetDestination(session,
                    Constants.ACCOUNTING_CUSTOMER_UPDATE_QUEUE);
                // Create a consumer
                using (IMessageConsumer consumer = session.CreateConsumer(destination))
                {
                    connection.Start();
                    do
                    {
                    } while (consumer.Receive(new TimeSpan(0, 0, 0, 1)) != null);
                }
            }
        }

        #endregion

        #region GetNextOrderNumber

        [TestMethod]
        public void TestGetNextOrderNumber()
        {
            int number1;
            int number2;

            number1 = services.GetNextOrderNumber();
            number2 = services.GetNextOrderNumber();

            Assert.AreEqual(number1, number2 - 1);
        }

        #endregion

        #region IsStandingValid

        //Good standing - run first
        [TestMethod]
        public void TestIsStandingValid()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrder");

            //Execute
            StandingReport res = services.IsStandingValid(xmlOrder);
            //Test

            Assert.AreEqual(res.IsStandingValid, true);
        }

        //Bad Standing
        [TestMethod]
        public void TestIsStandingValidBadStanding()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrderBadStanding");

            //Execute
            StandingReport res = services.IsStandingValid(xmlOrder);

            //Test
            Assert.AreEqual(res.IsStandingValid, false);
            Assert.AreEqual(res.BadStandingReason, "Credit limit exceeded");
        }

        //Invalid customer
        [TestMethod]
        public void TestIsStandingValidInvalidCustomer()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrderNoExsistingCustomer");

            //Execute
            StandingReport res = services.IsStandingValid(xmlOrder);

            //Test
            Assert.AreEqual(res.IsStandingValid, false);
        }

        //Invalid format
        [TestMethod]
        public void TestIsStandingValidInvalidFormat()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrderInvalidFormat");

            //Execute
            StandingReport res = services.IsStandingValid(xmlOrder);

            //Test
            Assert.AreEqual(res.IsStandingValid, false);
            Assert.AreEqual(res.BadStandingReason, "Invalid document");
        }

        //Empty document
        [TestMethod]
        public void TestIsStandingValidEmptyDocument()
        {
            //Setup
            string xmlOrder = string.Empty;

            //Execute
            StandingReport res = services.IsStandingValid(xmlOrder);

            //Test
            Assert.AreEqual(res.IsStandingValid, false);
            Assert.AreEqual(res.BadStandingReason, "Invalid document");
        }

        #endregion

        #region OrderShipped

        //Good shipment
        [TestMethod]
        public void TestOrderShipped()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrder");
            //Execute
            ShipOrderReport res = services.OrderShipped(xmlOrder);
            //Test
            Assert.AreEqual(res.IsSuccesfull, true);
        }

        //Empty document
        [TestMethod]
        public void TestOrderShippedEmptyDocument()
        {
            //Setup
            string xmlOrder = string.Empty;
            //Execute
            ShipOrderReport res = services.OrderShipped(xmlOrder);
            //Test
            Assert.AreEqual(res.IsSuccesfull, false);
            Assert.AreEqual(res.ErrorReason, "Invalid document");
        }

        //Empty document
        [TestMethod]
        public void TestOrderShippedInvalidFormat()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrderInvalidFormat");
            //Execute
            ShipOrderReport res = services.OrderShipped(xmlOrder);
            //Test
            Assert.AreEqual(res.IsSuccesfull, false);
            Assert.AreEqual(res.ErrorReason, "Invalid document");
        }

        //NonExsisting Order
        [TestMethod]
        public void TestOrderShippedNonExsistingOrder()
        {
            //Setup
            string xmlOrder = GetTestXml("TestOrderNoExsistingOrder");
            //Execute
            ShipOrderReport res = services.OrderShipped(xmlOrder);
            //Test
            Assert.AreEqual(res.IsSuccesfull, false);
            Assert.AreEqual(res.ErrorReason, "Invalid OrderId");
        }

        #endregion

        #region UpdateCustomer

        //Good update
        [TestMethod]
        public void TestUpdateCustomer()
        {
            //Setup
            string xmlOrder = GetTestXml("TestCustomerUpdate");
            //Execute
            CustomerUpdateReport res = services.UpdateCustomer(xmlOrder);
            //Test
            Assert.AreEqual(res.IsSuccesfull, true);
            using (var context = new WGRUSEntities())
            {
                Customer c = context.Customers.Find(12345678);
                Assert.AreEqual(c.Gade, "Boulevarden 25");
            }
        }

        //Good create
        [TestMethod]
        public void TestUpdateCustomerCreate()
        {
            //Setup
            string xmlOrder = GetTestXml("TestCustomerCreate");
            //Execute
            CustomerUpdateReport res = services.UpdateCustomer(xmlOrder);
            //Test
            Assert.AreEqual(res.IsSuccesfull, true);
            using (var context = new WGRUSEntities())
            {
                Customer c = context.Customers.Find(87654321);
                Assert.IsNotNull(c);
                if (c != null)
                {
                    Assert.AreEqual(c.Navn, "Campus Vejle");
                    Assert.AreEqual(c.Gade, "Boulevarden 48");
                    Assert.AreEqual(c.PostNr, 7100);
                    Assert.AreEqual(c.By, "Vejle");
                    Assert.AreEqual(c.Email, "test@vejlehs.dk");
                    Assert.AreEqual(c.CreditLimit, 0);
                    Assert.IsFalse(c.Approved);
                }
            }
        }


        //Invalid format
        [TestMethod]
        public void TestUpdateCustomerInvalidFormat()
        {
            //Setup
            string xmlOrder = GetTestXml("TestCustomerInvalidFormat");
            //Execute
            CustomerUpdateReport res = services.UpdateCustomer(xmlOrder);
            //Test
            //Test
            Assert.AreEqual(res.IsSuccesfull, false);
            Assert.AreEqual(res.ErrorReason, "Invalid document");
        }

        //Empty document
        [TestMethod]
        public void TestUpdateCustomerEmptyDocument()
        {
            //Setup
            string xmlOrder = string.Empty;
            //Execute
            CustomerUpdateReport res = services.UpdateCustomer(xmlOrder);
            //Test
            //Test
            Assert.AreEqual(res.IsSuccesfull, false);
            Assert.AreEqual(res.ErrorReason, "Invalid document");
        }

        [TestMethod]
        public void TestSignalCustomerCreate()
        {
            DateTime oprettet = DateTime.Now;
            Customer c;
            using (var db = new WGRUSEntities())
            {
                //Setup
                c = new Customer
                {
                    Approved = false,
                    By = "Vejle",
                    CreditLimit = 10000,
                    Email = "a@b.c",
                    Gade = "Gade1",
                    Navn = "Internal",
                    Oprettet = oprettet,
                    PostNr = 7100,
                    TelefonNr = 55555555
                };
                //Execute
                db.Customers.Add(c);
                db.SaveChanges();
            }

            //Test
            IMessage message = GetMessage();
            Assert.IsNotNull(message);
            var m = message as ITextMessage;
            Assert.IsNotNull(m);
            string strXml = m.Text;
            Assert.AreNotEqual(string.IsNullOrEmpty(strXml), true);
            XDocument doc = LoadMyXml(strXml);
            Assert.IsNotNull(doc);
            //Linq to xml
            // Do a simple query and print the results to the console
            XNamespace ns = "http://wgrus.com/Accounting";

            var d = (from item in doc.Descendants(ns + "Customer")
                     select new
                     {
                         id = item.Element("CustomerId").Value,
                         navn = item.Element("Navn").Value,
                         gade = item.Element("Gade").Value,
                         zip = item.Element("PostNr").Value,
                         city = item.Element("By").Value,
                         oprettet = item.Element("Oprettet").Value,
                         email = item.Element("Email").Value
                     }).First();
            DateTime dt = DateTime.Parse(d.oprettet, CultureInfo.InvariantCulture);
            Assert.AreEqual(c.TelefonNr.ToString(), d.id);
            Assert.AreEqual(c.Navn, d.navn);
            Assert.AreEqual(c.Gade, d.gade);
            Assert.AreEqual(c.PostNr.ToString(), d.zip);
            Assert.AreEqual(c.By, d.city);
            Assert.AreEqual(c.Oprettet, dt);
            Assert.AreEqual(c.Email, d.email);
        }

        [TestMethod]
        public void TestSignalCustomerUpdate()
        {
            DateTime oprettet = DateTime.Now;
            Customer c;
            using (var db = new WGRUSEntities())
            {
                //Setup
                c = db.Customers.Find(55555555);
                c.By = "Fredecia";
                c.Email = "w@t.u";
                c.Gade = "Nygade";
                c.Navn = "Nynavn";
                c.PostNr = 5000;
                //Execute
                db.SaveChanges();
            }

            //Test
            IMessage message = GetMessage();
            Assert.IsNotNull(message);
            var m = message as ITextMessage;
            Assert.IsNotNull(m);
            string strXml = m.Text;
            Assert.AreNotEqual(string.IsNullOrEmpty(strXml), true);
            XDocument doc = LoadMyXml(strXml);
            Assert.IsNotNull(doc);
            //Linq to xml
            // Do a simple query and print the results to the console
            XNamespace ns = "http://wgrus.com/Accounting";

            var d = (from item in doc.Descendants(ns + "Customer")
                     select new
                     {
                         id = item.Element("CustomerId").Value,
                         navn = item.Element("Navn").Value,
                         gade = item.Element("Gade").Value,
                         zip = item.Element("PostNr").Value,
                         city = item.Element("By").Value,
                         oprettet = item.Element("Oprettet").Value,
                         email = item.Element("Email").Value
                     }).First();
            DateTime dt = DateTime.Parse(d.oprettet, CultureInfo.InvariantCulture);
            Assert.AreEqual(c.TelefonNr.ToString(), d.id);
            Assert.AreEqual(c.Navn, d.navn);
            Assert.AreEqual(c.Gade, d.gade);
            Assert.AreEqual(c.PostNr.ToString(), d.zip);
            Assert.AreEqual(c.By, d.city);
            Assert.AreEqual(c.Oprettet, dt);
            Assert.AreEqual(c.Email, d.email);
        }



        #endregion

        /// <summary>
        /// Helper function
        /// </summary>
        /// <param name="resourceName"></param>
        /// <returns></returns>
        private string GetTestXml(string resourceName)
        {
            var xml = Resources.ResourceManager.GetObject(resourceName);
            return xml.ToString();
        }

        private IMessage GetMessage()
        {
            IMessage res;
            using (IConnection connection = factory.CreateConnection())
            using (ISession session = connection.CreateSession())
            {
                IDestination destination = SessionUtil.GetDestination(session,
                    Constants.ACCOUNTING_CUSTOMER_UPDATE_QUEUE);
                // Create a consumer
                using (IMessageConsumer consumer = session.CreateConsumer(destination))
                {
                    connection.Start();
                    res = consumer.Receive(new TimeSpan(0, 0, 0, 5));
                }
            }
            return res;
        }

        private XDocument LoadMyXml(string xmlString)
        {
            XDocument doc=null;
            try
            {
                //Validate XML velformed
                doc = XDocument.Parse(xmlString);
            }
            catch (Exception e)
            {

            }
            return doc;
        }

    }
}